package com.yun.zf.app.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yun.zf.app.mapper.ZfCommunityMapper;
import com.yun.zf.app.mapper.ZfCommunityPictureMapper;
import com.yun.zf.app.service.ZfCommunityService;
import com.yun.zf.app.service.ZfHouseBasicService;
import com.yun.zf.common.admin.dto.community.AgentInfoDto;
import com.yun.zf.common.admin.dto.community.CommunityBasicDto;
import com.yun.zf.common.admin.dto.community.CommunityDto;
import com.yun.zf.common.admin.dto.community.CommunityPictureDto;
import com.yun.zf.common.admin.model.house.HouseListMo;
import com.yun.zf.common.admin.model.search.CommunityIndexKey;
import com.yun.zf.common.admin.model.search.CommunitySearchMo;
import com.yun.zf.common.app.domain.ZfCommunity;
import com.yun.zf.common.app.dto.community.CommunityTotal;
import com.yun.zf.common.app.dto.detail.CommunityNearByDto;
import com.yun.zf.common.constant.Constants;
import com.yun.zf.common.esRes.CommunityResMo;
import com.yun.zf.common.mapstruct.admin.CommunityMapper;
import com.yun.zf.system.service.SysAgentService;
import com.yun.zf.system.utils.EsRestUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 社区表 服务实现类ø
 * </p>
 *
 * @author cj
 * @since 2021-01-29
 */
@Service
@Slf4j
public class ZfCommunityServiceImpl extends ServiceImpl<ZfCommunityMapper, ZfCommunity> implements ZfCommunityService {

    @Autowired
    private EsRestUtil esRestUtil;
    @Autowired
    private ZfCommunityPictureMapper pictureMapper;
    @Autowired
    private ZfHouseBasicService basicService;
    @Autowired
    private SysAgentService agentService;

    /**
     * 首页获取品质小区推荐前5条
     *
     * @return
     */
    @Override
    public Page<CommunityNearByDto> getBrandCommunity(Long cityCode,int current,int pageSize) {
        // 获取品质小区
        Page<CommunityNearByDto> page = new Page<>(current, pageSize);
        List<CommunityNearByDto> brandDtoList = baseMapper.getBrandCommunity(cityCode,page);
        for (CommunityNearByDto c: brandDtoList
             ) {
    // todo
            List<CommunityTotal> total =  baseMapper.ctotal(Long.parseLong(c.getId()));
            for (CommunityTotal t: total
                 ) {
                if (t.getType()==1){
                    c.setRentTotal(t.getTotal());
                }
                if (t.getType()==2){
                    c.setSoldTotal(t.getTotal());
                }
            }
        }

        page.setRecords(brandDtoList);

        return page;
    }

    @Override
    public CommunityNearByDto findommunityBasic(Long communityId) {

        return baseMapper.getCommunityInfo(communityId);
    }

    @Override
    public ZfCommunity getCommunity(Long communityId, Long provinceCode, Long cityCode) {
        QueryWrapper<ZfCommunity> communityQueryWrapper = new QueryWrapper<>();
        communityQueryWrapper.lambda().eq(ZfCommunity::getCityCode, cityCode).eq(ZfCommunity::getProvinceCode, provinceCode).eq(ZfCommunity::getId, communityId);
        return baseMapper.selectOne(communityQueryWrapper);
    }

    @Override
    public List<CommunityNearByDto> getBasicCommunity(List<Long> ids) {
        List<CommunityNearByDto> list = baseMapper.getBasicCommunity(ids);
        for (CommunityNearByDto c: list
        ) {
            // todo
            List<CommunityTotal> total =  baseMapper.ctotal(Long.parseLong(c.getId()));
            for (CommunityTotal t: total
            ) {
                if (t.getType()==1){
                    c.setRentTotal(t.getTotal());
                }
                if (t.getType()==2){
                    c.setSoldTotal(t.getTotal());
                }
            }
        }
        return  list;
    }


    @Override
    public CommunityBasicDto getBasic(Long communityId) {
        //1、 获取基本信息
        QueryWrapper<ZfCommunity> communityQueryWrapper = new QueryWrapper<>();
        communityQueryWrapper.lambda().eq(ZfCommunity::getId, communityId);
        ZfCommunity community = baseMapper.selectOne(communityQueryWrapper);
        // 数据转换
        return  CommunityMapper.INSTANCE.communityDoToMo(community);
    }

    @Override
    public Map<String, Object> searchCommunitys(CommunitySearchMo communitySearchMo) {
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
        String[] fields = {CommunityIndexKey.CID};
        //1 、 构建搜索条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 城市代码必须
        queryBuilder.must(QueryBuilders.termQuery(CommunityIndexKey.CITYCODE, communitySearchMo.getCityCode()));
        // 区域街道代码搜索
        if (StringUtils.isNotEmpty(communitySearchMo.getRegionCode())) {
            queryBuilder.must(QueryBuilders.termQuery(CommunityIndexKey.REGIONCODE, communitySearchMo.getRegionCode()));
        }
        if (StringUtils.isNotEmpty(communitySearchMo.getStreetCode())) {
            queryBuilder.must(QueryBuilders.termQuery(CommunityIndexKey.STREETCODE, communitySearchMo.getStreetCode()));
        }

        // 如果搜索框内容不为空
        if (StringUtils.isNotBlank(communitySearchMo.getContext())) {
            if (StringUtils.isEmpty(communitySearchMo.getCommunityType()) || "C".equals(communitySearchMo.getCommunityType())) {
                queryBuilder.must(QueryBuilders.matchQuery(CommunityIndexKey.COMMUNITYNAME, communitySearchMo.getContext()).boost(2.0f));
            }
            // 如果为商圈，搜索补全接口会返回是商圈或者小区
            else if ("B".equals(communitySearchMo.getCommunityType())) {
                queryBuilder.must(QueryBuilders.matchQuery(CommunityIndexKey.BUSINESS, communitySearchMo.getContext()).boost(2.0f));
            } else if ("S".equals(communitySearchMo.getCommunityType())) {
                queryBuilder.filter(QueryBuilders.termQuery(CommunityIndexKey.EDUSCHOOLS, communitySearchMo.getContext()).boost(2.0f));
            }

        }

        // 如果均价区间不为空则加上均价搜索
        if (StringUtils.isNotBlank(communitySearchMo.getAveragePrice())) {
            String minPrice = communitySearchMo.getAveragePrice().split("-")[0];
            String maxPrice = communitySearchMo.getAveragePrice().split("-")[1];
            queryBuilder.filter(QueryBuilders.rangeQuery(CommunityIndexKey.AVERAGEPRICE).gte(minPrice).lte(maxPrice));
        }
        // 如果楼龄不为空，则获取符合条件的楼龄范围
        if (StringUtils.isNotBlank(communitySearchMo.getCtyBuildYear())) {
            int nowYear = DateUtil.thisYear();
            int minYear = nowYear - Integer.parseInt(communitySearchMo.getCtyBuildYear());
            queryBuilder.filter(QueryBuilders.rangeQuery(CommunityIndexKey.CTYBUILDYEAR).gte(minYear).lte(nowYear));
        }
        // 如果地铁不为空
        if (StringUtils.isNotEmpty(communitySearchMo.getStations())) {
            String[] stations = communitySearchMo.getStations().split(",");
            queryBuilder.filter(QueryBuilders.termsQuery(CommunityIndexKey.COMMUNITYSTATIONS, stations));
        }
        searchQueryBuilder.withQuery(queryBuilder).withFields(fields);
        try {
            Map<String, Object> communityData = esRestUtil.searchDataPage(Constants.ES_COMMUNITY_INDEX, communitySearchMo.getCurrent(), communitySearchMo.getPageSize(), CommunityResMo.class, searchQueryBuilder);

            return communityData;
        } catch (Exception e) {

        }

        return null;
    }

    /**
     * 获取小区详情信息
     * @param communityId
     * @return
     */
    @Override
    public CommunityDto getDetailInfo(Long communityId) {
        CommunityDto mo = new CommunityDto();
        //1、 获取小区基本信息
        CommunityBasicDto basic = this.getBasic(communityId);
        //2.获取小区图片集合
        List<CommunityPictureDto> pictureList = pictureMapper.getPictureByCid(communityId,-1);
        Map<Integer, List<CommunityPictureDto>> groupBy = pictureList.stream().collect(Collectors.groupingBy(CommunityPictureDto::getType));
        // 封面图
        mo.setCover(groupBy.get(0));
        // 获取户型图
        mo.setHxPic(groupBy.get(3));
        // 小区环境图
        mo.setPictureList(groupBy.get(1));
        // 获取小区在售房源信息
        Page<HouseListMo> sold = basicService.houseBasic(Long.parseLong(basic.getProvinceCode()) ,Long.parseLong(basic.getCityCode()) , communityId, 2,-1L, 1, 5);
        // 获取在租房源信息
        Page<HouseListMo> rent = basicService.houseBasic(Long.parseLong(basic.getProvinceCode()) ,Long.parseLong(basic.getCityCode()), communityId, 1,-1L, 1, 5);
        // 获取经纪人信息
        List<AgentInfoDto> agentDtos = agentService.getAgentByCommunityId(communityId);
        //如果经纬度不为空则 获取附近小区
        List<CommunityNearByDto> nearCommunity= null;
        String location =basic.getLocation();
        if (StringUtils.isNotBlank(location)){
            double lat =Double.parseDouble( location.split(",")[1]);
            double lon =Double.parseDouble( location.split(",")[0]);
            nearCommunity=  this.nearCommunityList(communityId,lat,lon,1000);
        }
        mo.setBasicDto(basic);
        mo.setSold(sold);
        mo.setRent(rent);
        mo.setAgents(agentDtos);
        mo.setNearCommunity(nearCommunity);
        return mo;
    }

    /**
     * 根据小区id和经纬度获取附近小区信息
     * @param communityId
     * @param lat
     * @param lon
     * @param distance
     * @return
     */
    @Override
    public List<CommunityNearByDto> nearCommunityList(Long communityId, double lat, double lon, double distance) {
        GeoDistanceQueryBuilder builder =
                QueryBuilders.geoDistanceQuery("point")//查询字段
                        .point(lat, lon)//设置经纬度
                        .distance(distance, DistanceUnit.METERS)//设置距离和单位（米）
                        .geoDistance(GeoDistance.ARC);
        GeoDistanceSortBuilder sortBuilder =
                SortBuilders.geoDistanceSort("point",lat,lon)
                        .point(lat, lon)
                        .unit(DistanceUnit.METERS)
                        .order(SortOrder.ASC);//排序方式

        String[] fields = {CommunityIndexKey.CID};
        //1 、 构建搜索条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.filter(builder);

        //构造查询条件
        NativeSearchQueryBuilder nativeSearchQueryBuilder =
                new NativeSearchQueryBuilder()
                        .withQuery(queryBuilder)
                        .withSort(sortBuilder)
                        .withFields(fields);

        Map<String, Object> communityData = esRestUtil.searchDataPage(Constants.ES_COMMUNITY_INDEX,1,10, CommunityResMo.class,nativeSearchQueryBuilder);
        int total = Integer.parseInt(communityData.get("total").toString());
        List<CommunityNearByDto> nearCommunityList=null;
        if (total>0){
            List<CommunityResMo> esResList = (List<CommunityResMo>) communityData.get("records");
            List<Long> ids = esResList.stream().map(c -> c.getCid()).collect(Collectors.toList());
            // 移除本身房源小区
            ids.remove(communityId);
            if (ids==null||ids.size()==0){
                return  null;
            }
            nearCommunityList=  this.getBasicCommunity(ids);
        }
        return nearCommunityList;
    }
}
